<template>
  <div class="media-uploader">
    <div class="media-list">
      <div v-for="(item, idx) in fileList" :key="idx" class="media-thumb" @click="handlePreview(idx)">
        <img v-if="item.type.startsWith('image/')" :src="item.url" class="thumb-img" />
        <div v-else-if="item.type.startsWith('video/')" class="thumb-video">
          <video :src="item.url" class="thumb-img" muted />
          <span class="video-icon">▶</span>
        </div>
        <!-- 上传中的遮罩 -->
        <div v-if="item.uploading" class="uploading-mask">
          <i class="el-icon-loading"></i>
        </div>
        <i class="el-icon-close close-btn" @click.stop="removeFile(idx)"></i>
      </div>
      <div v-if="fileList.length < limit" class="media-thumb upload-btn" @click="triggerInput">
        <i class="el-icon-plus" style="font-size:28px;color:#8c939d;" />
        <input ref="input" type="file" :accept="getAcceptTypes()" :multiple="acceptType !== 'video'"
          style="display:none" @change="handleChange" />
      </div>
    </div>
    <!-- 预览弹窗 -->
    <el-dialog v-model="preview.visible" width="60%" :show-close="true" append-to-body>
      <div v-if="preview.current">
        <img v-if="preview.current.type.startsWith('image/')" :src="preview.current.url"
          style="max-width:100%;max-height:60vh;" />
        <video v-else-if="preview.current.type.startsWith('video/')" :src="preview.current.url" controls
          style="max-width:100%;max-height:60vh;" />
        <div class="media-list-preview-bar">
          <div v-for="(item, idx) in fileList" :key="idx" class="preview-thumb"
            :class="{ active: idx === preview.index }" @click="handlePreview(idx)">
            <img v-if="item.type.startsWith('image/')" :src="item.url" />
            <video v-else-if="item.type.startsWith('video/')" :src="item.url" muted />
          </div>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { upload } from "@/api/index";
export default {
  name: "MediaUploader",
  props: {
    modelValue: {
      type: Array,
      default: () => [],
    },
    limit: {
      type: Number,
      default: 9,
    },
    // 允许的文件类型：'image', 'video', 'all'
    acceptType: {
      type: String,
      default: 'all'
    }
  },
  emits: ["update:modelValue"],
  data() {
    return {
      fileList: [],
      preview: {
        visible: false,
        index: 0,
        current: null,
      },
    };
  },
  watch: {
    modelValue: {
      immediate: true,
      handler(val) {
        this.fileList = val || [];
      },
    },
    fileList: {
      deep: true,
      handler(val) {
        this.$emit("update:modelValue", val);
      },
    },
  },
  methods: {
    triggerInput() {
      this.$refs.input && this.$refs.input.click();
    },
    async handleChange(e) {
      const files = Array.from(e.target.files);
      for (const file of files) {
        // 检查文件类型
        if (!this.isValidFileType(file)) {
          this.$message.error(this.getTypeErrorMessage());
          continue;
        }
        if (this.fileList.length >= this.limit) break;

        // 创建预览URL
        const previewUrl = URL.createObjectURL(file);

        // 添加到文件列表（先显示预览）
        const fileItem = {
          name: file.name,
          url: previewUrl,
          type: file.type,
          raw: file,
          uploading: true, // 标记正在上传
        };
        this.fileList.push(fileItem);

        try {
          // 上传文件
          const formData = new FormData();
          formData.append("file", file);
          const res = await upload(formData);

          // 上传成功，更新文件信息
          // if (res.data && res.data[0] && res.data[0].fileName) {
          //   const serverUrl = `https://www.yaozhuasocial.com/imgs/${res.data[0].fileName}`;
          if (res.data && res.data) {
            const serverUrl = res.data;
            const fileIndex = this.fileList.indexOf(fileItem);
            if (fileIndex > -1) {
              // 直接替换整个对象来确保响应式更新
              this.fileList.splice(fileIndex, 1, {
                ...fileItem,
                url: serverUrl,
                serverFileName: res.data[0].fileName,
                uploading: false
              });
            }
            // 释放预览URL
            URL.revokeObjectURL(previewUrl);
          } else {
            // 如果没有返回文件名，也要停止loading状态
            const fileIndex = this.fileList.indexOf(fileItem);
            if (fileIndex > -1) {
              this.fileList.splice(fileIndex, 1, {
                ...fileItem,
                uploading: false
              });
            }
            this.$message.error("上传响应格式错误");
          }
        } catch (error) {
          console.error("上传失败:", error);
          this.$message.error("上传失败，请重试");
          // 移除上传失败的文件
          const index = this.fileList.indexOf(fileItem);
          if (index > -1) {
            this.fileList.splice(index, 1);
          }
          URL.revokeObjectURL(previewUrl);
        }
      }
      e.target.value = "";
    },
    removeFile(idx) {
      const file = this.fileList[idx];
      // 如果是本地预览URL，需要释放
      if (file.url && file.url.startsWith('blob:')) {
        URL.revokeObjectURL(file.url);
      }
      this.fileList.splice(idx, 1);
    },
    handlePreview(idx) {
      this.preview.index = idx;
      this.preview.current = this.fileList[idx];
      this.preview.visible = true;
    },
    getAcceptTypes() {
      switch (this.acceptType) {
        case 'image':
          return 'image/*';
        case 'video':
          return 'video/*';
        default:
          return 'image/*,video/*';
      }
    },
    isValidFileType(file) {
      switch (this.acceptType) {
        case 'image':
          return file.type.startsWith('image/');
        case 'video':
          return file.type.startsWith('video/');
        default:
          return file.type.startsWith('image/') || file.type.startsWith('video/');
      }
    },
    getTypeErrorMessage() {
      switch (this.acceptType) {
        case 'image':
          return '只能上传图片文件';
        case 'video':
          return '只能上传视频文件';
        default:
          return '只能上传图片或视频文件';
      }
    },
  },
};
</script>

<style scoped>
.media-uploader {
  width: 100%;
}

.media-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.media-thumb {
  width: 80px;
  height: 80px;
  border-radius: 4px;
  background: #f5f5f5;
  position: relative;
  overflow: hidden;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.thumb-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.thumb-video {
  width: 100%;
  height: 100%;
  position: relative;
}

.video-icon {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  padding: 6px 10px;
  font-size: 22px;
  pointer-events: none;
}

.close-btn {
  position: absolute;
  top: 2px;
  right: 2px;
  color: #fff;
  background: rgba(0, 0, 0, 0.4);
  border-radius: 50%;
  font-size: 16px;
  cursor: pointer;
  z-index: 2;
}

.upload-btn {
  border: 1px dashed #d9d9d9;
  background: #fafafa;
  justify-content: center;
  align-items: center;
}

.media-list-preview-bar {
  display: flex;
  gap: 6px;
  margin-top: 12px;
  overflow-x: auto;
}

.preview-thumb {
  width: 40px;
  height: 40px;
  border: 2px solid transparent;
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
}

.preview-thumb.active {
  border-color: #409EFF;
}

.preview-thumb img,
.preview-thumb video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.uploading-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 20px;
}
</style>